package com.tools.scanner.ui.qrcode.creator.impl

import android.os.Bundle
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import com.tools.scanner.R
import com.tools.scanner.bean.BarcodeSchema
import com.tools.scanner.databinding.FragmentBarcodeInputBinding

class CreateBarcodeFragment : BaseCreateFragment() {

    companion object {

        private const val CREATE_SCHEMA = "create_schema"

        fun newInstance(schema: BarcodeSchema): CreateBarcodeFragment {
            val bundle = Bundle()
            bundle.putString(CREATE_SCHEMA, schema.name)

            val fragment = CreateBarcodeFragment()
            fragment.arguments = bundle
            return fragment
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putString(CREATE_SCHEMA, mBarcodeSchema?.name)
    }

    private lateinit var mBinding: FragmentBarcodeInputBinding
    private var mBarcodeSchema: BarcodeSchema? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mBinding = FragmentBarcodeInputBinding.inflate(inflater, container, false)
        return mBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val schemaName: String? = if (savedInstanceState != null) {
            savedInstanceState.getString(CREATE_SCHEMA)
        } else {
            arguments?.getString(CREATE_SCHEMA)
        }

        if (schemaName == null) {
            return
        }

        mBarcodeSchema = BarcodeSchema.valueOf(schemaName)

        when (mBarcodeSchema) {
            BarcodeSchema.AZTEC -> {
                mBinding.editText.setHint(R.string.input_hint_aztec)
                mBinding.editText.addTextChangedListener(AZTECTextWatcher(mBinding.editText))
            }

            BarcodeSchema.CODABAR -> {
                mBinding.editText.setHint(R.string.input_hint_codabar)
                mBinding.editText.addTextChangedListener(CODABARTextWatcher(mBinding.editText))
            }

            BarcodeSchema.CODE_39 -> {
                mBinding.editText.setHint(R.string.input_hint_code_39)
                mBinding.editText.addTextChangedListener(CODE39TextWatcher(mBinding.editText))
            }

            BarcodeSchema.CODE_93 -> {
                mBinding.editText.setHint(R.string.input_hint_code_93)
                mBinding.editText.addTextChangedListener(CODE93TextWatcher(mBinding.editText))
            }

            BarcodeSchema.CODE_128 -> {
                mBinding.editText.setHint(R.string.input_hint_code_128)
                mBinding.editText.addTextChangedListener(CODE128TextWatcher(mBinding.editText))
            }

            BarcodeSchema.DATA_MATRIX -> {
                mBinding.editText.setHint(R.string.input_hint_data_matrix)
                mBinding.editText.addTextChangedListener(DataMatrixTextWatcher(mBinding.editText))
            }

            BarcodeSchema.EAN_8 -> {
                mBinding.editText.setHint(R.string.input_hint_ean_8)
                mBinding.editText.addTextChangedListener(ENA8TextWatcher(mBinding.editText))
            }

            BarcodeSchema.EAN_13 -> {
                mBinding.editText.setHint(R.string.input_hint_ean_13)
                mBinding.editText.addTextChangedListener(EAN13TextWatcher(mBinding.editText))
            }

            BarcodeSchema.ITF -> {
                mBinding.editText.setHint(R.string.input_hint_itf)
                mBinding.editText.addTextChangedListener(ITFTextWatcher(mBinding.editText))
            }

            BarcodeSchema.PDF_417 -> {
                mBinding.editText.setHint(R.string.input_hint_pdf417)
                mBinding.editText.addTextChangedListener(Pdf417TextWatcher(mBinding.editText))
            }

            BarcodeSchema.UPC_A -> {
                mBinding.editText.setHint(R.string.input_hint_upc_a)
                mBinding.editText.addTextChangedListener(UPCATextWatcher(mBinding.editText))
            }

            BarcodeSchema.UPC_E -> {
                mBinding.editText.setHint(R.string.input_hint_upc_e)
                mBinding.editText.addTextChangedListener(UPCETextWatcher(mBinding.editText))
            }

            else -> {}
        }
    }

    override fun checkParams(): Boolean {
        val barcode = mBinding.editText.text.toString()

        return when (mBarcodeSchema) {
            // AZTEC，CODE 128，DATA MATRIX，PDF417 可以是任意字符
            BarcodeSchema.AZTEC,
            BarcodeSchema.DATA_MATRIX,
            BarcodeSchema.PDF_417 -> {
                !TextUtils.isEmpty(barcode)
            }

            BarcodeSchema.CODE_128->barcode.matches(Regex("^[\\x00-\\x7F]*\$")) // 只支持 A, B, C, D 和数字 0-9
            BarcodeSchema.CODABAR -> barcode.matches(Regex("^[ABCD][ABCD0-9\\-\\$:\\/\\.]*[ABCD]$")) // 只支持 A, B, C, D 和数字 0-9
            BarcodeSchema.CODE_39 -> barcode.matches(Regex("^[A-Z0-9 \$%&'*+/.-]*\$")) // 支持 A-Z, 0-9, 空格和一些符号
            BarcodeSchema.CODE_93 -> barcode.matches(Regex("^[A-Z0-9 \$%&'*+/.-]*\$")) // 支持字母和数字
            BarcodeSchema.EAN_8 -> barcode.matches(Regex("^\\d{7}$")) // 必须是 8 位数字
            BarcodeSchema.EAN_13 -> barcode.matches(Regex("^\\d{12}$")) // 必须是 12 位数字
            BarcodeSchema.ITF -> barcode.matches(Regex("^\\d{2,14}$")) && barcode.length % 2 == 0 // 偶数位数字
            BarcodeSchema.UPC_A -> barcode.matches(Regex("^\\d{11}$")) // 必须是 12 位数字
            BarcodeSchema.UPC_E -> barcode.matches(Regex("^\\d{7}$")) // 必须是 8 位数字
            else -> false
        }
    }

    override fun createQrCodeContent(): String {
        return mBinding.editText.text.toString()
    }
}

class AZTECTextWatcher(private val editText: EditText) : BarcodeTextWatcher() {

    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许字母、数字和某些特定字符
        val input = editable.toString()
        val regex = Regex("^[A-Za-z0-9]*$") // 只允许字母和数字
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^A-Za-z0-9]"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }
    }
}

class CODABARTextWatcher(private val editText: EditText) : BarcodeTextWatcher() {

    private var isUpdating = false // 防止无限循环

    override fun afterTextChanged(editable: Editable?) {
        if (isUpdating) return // 避免递归调用

        val input = editable.toString()
        // CODABAR 允许的字符集
        val regex = Regex("^[ABCD0-9\\-\\$:\\/\\.]*$")

        // 检查输入是否符合 CODABAR 的正则表达式
        if (!regex.matches(input)) {
            isUpdating = true // 设置标志，防止递归调用
            // 过滤掉不符合的字符
            val filteredInput = input.filter { regex.matches(it.toString()) }
            editText.setText(filteredInput)
            editText.setSelection(filteredInput.length) // 移动光标到末尾
            isUpdating = false // 重置标志
        }
    }
}

class CODE39TextWatcher(private val editText: EditText) : BarcodeTextWatcher() {

    private var isUpdating = false

    override fun afterTextChanged(editable: Editable?) {
        if (isUpdating) return // 防止无限循环

        val input = editable.toString()
        val regex = Regex("^[A-Z0-9 \$%&'*+/.-]*$")

        if (!regex.matches(input)) {
            isUpdating = true // 设置标志，防止递归调用
            val filteredInput = input.filter { regex.matches(it.toString()) }
            editText.setText(filteredInput)
            editText.setSelection(filteredInput.length)
            isUpdating = false // 重置标志
        }
    }
}

class CODE93TextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 获取当前输入
        val input = editable.toString()
        // CODE93 允许的字符集
        val regex = Regex("^[A-Z0-9 \$%&'*+/.-]*$")

        // 检查输入是否符合 CODE93 的正则表达式
        if (!regex.matches(input)) {
            // 过滤掉不符合的字符，并更新 EditText
            val filteredInput = input.filter { regex.matches(it.toString()) }
            editText.setText(filteredInput)
            // 移动光标到末尾
            editText.setSelection(filteredInput.length)
        }
    }

}

class CODE128TextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    private var isUpdating = false // 防止无限循环

    override fun afterTextChanged(editable: Editable?) {
        if (isUpdating) return // 避免递归调用

        val input = editable.toString()
        val regex = Regex("^[\\x00-\\x7F]*$") // 只允许 ASCII 字符

        // 检查输入是否符合 ASCII 字符的正则表达式
        if (!regex.matches(input)) {
            isUpdating = true // 设置标志，防止递归调用
            // 过滤掉不符合的字符
            val filteredInput = input.filter { regex.matches(it.toString()) }
            editText.setText(filteredInput)
            editText.setSelection(filteredInput.length) // 移动光标到末尾
            isUpdating = false // 重置标志
        }
    }
}

class DataMatrixTextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：允许所有 ASCII 字符（0-127）
        val input = editable.toString()
        val regex = Regex("^[\\x00-\\x7F]*$") // 只允许 ASCII 字符
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^\\x00-\\x7F]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }
    }
}

class ENA8TextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许 EAN-8 类型的数字
        val input = editable.toString()
        val regex = Regex("^[0-9]*$") // 只允许数字
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^0-9]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }

        // 限制输入长度为 8 位
        if (input.length > 7) {
            editText.setText(input.substring(0, 7))
            editText.setSelection(7) // 移动光标到末尾
        }
    }
}

class EAN13TextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许 EAN-13 类型的数字
        val input = editable.toString()
        val regex = Regex("^[0-9]*$") // 只允许数字
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^0-9]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }

        // 限制输入长度为 13 位
        if (input.length > 12) {
            editText.setText(input.substring(0, 12))
            editText.setSelection(12) // 移动光标到末尾
        }
    }
}

class ITFTextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许 EAN-13 类型的数字
        val input = editable.toString()
        val regex = Regex("^[0-9]*$") // 只允许数字
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^0-9]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }

        // 限制输入长度为 14 位
        if (input.length > 14) {
            editText.setText(input.substring(0, 14))
            editText.setSelection(14) // 移动光标到末尾
        }
    }
}

class Pdf417TextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许有效的 ASCII 字符（0-127）
        val input = editable.toString()
        val regex = Regex("^[\\x00-\\x7F]*$") // 只允许 ASCII 字符
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^\\x00-\\x7F]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }

        // 可选：限制最大长度，例如 2700 字符（PDF417 的最大容量）
        if (input.length > 2700) {
            editText.setText(input.substring(0, 2700))
            editText.setSelection(2700) // 移动光标到末尾
        }
    }
}

class UPCATextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许 UPC-A 类型的数字
        val input = editable.toString()
        val regex = Regex("^[0-9]*$") // 只允许数字
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^0-9]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }

        // 限制输入长度为 12 位
        if (input.length > 11) {
            editText.setText(input.substring(0, 11))
            editText.setSelection(11) // 移动光标到末尾
        }
    }
}

class UPCETextWatcher(private val editText: EditText) : BarcodeTextWatcher() {
    override fun afterTextChanged(editable: Editable?) {
        // 输入限制：只允许 UPC-E 类型的数字
        val input = editable.toString()
        val regex = Regex("^[0-9]*$") // 只允许数字
        if (!regex.matches(input)) {
            editText.setText(input.replace(Regex("[^0-9]+"), ""))
            editText.setSelection(editText.text.length) // 移动光标到末尾
        }

        // 限制输入长度为 8 位
        if (input.length > 7) {
            editText.setText(input.substring(0, 7))
            editText.setSelection(7) // 移动光标到末尾
        }
    }
}

abstract class BarcodeTextWatcher : TextWatcher {
    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

    }

    override fun afterTextChanged(editable: Editable?) {

    }

}